/*
在模板模式（Template Pattern）中，一个抽象类公开定义了执行它的方法的方式/模板。
它的子类可以按需要重写方法实现，但调用将以抽象类中定义的方式进行。
这种类型的设计模式属于行为型模式。

模板方法适用于一次性实现算法的不变部分，而将可变的行为留给子类去实现。
各个子类的公共行为应当被提取到父类中以避免代码重复。
举个简单的例子，在购买东西的时候，我们一般可以分为三个步骤，拿东西，付钱，打包，那东西和打包的过程都是通用的，
而付钱这个过程有可能付美元，有可能付人民币。
在流程确定且具有公共方法的情况下，可以提取公共方法到父类，把付钱这个动作留给子类实现，

注意事项：为防止恶意操作，一般模板方法都加上 final 关键词。
*/

#include <memory>
#include <iostream>


class AbstractGame
{
public:
    AbstractGame() = default;
    virtual ~AbstractGame() {}

    /// 不同的游戏实现初始化等方法不一致，但是玩游戏的流程确定
    virtual void Init() = 0;  // 初始化游戏

    virtual void Start() = 0; // 开始游戏

    virtual void Stop() = 0;  // 结束游戏

    /// Play的流程确定，不需要派生类实现
    virtual void Play() final /*使用final防止派生类重写该方法*/{
        Init();
        Start();
        Stop();
    }
};

class Cricket : public AbstractGame
{
public:
    void Init(){
        std::cout << "Cricket Game Started. Enjoy the game!" << std::endl;
    }

    void Start(){
        std::cout << "Cricket Game Initialized! Start playing." << std::endl;
    }

    void Stop(){
        std::cout << "Cricket Game Finished!" << std::endl;
    }
};


class FootBall : public AbstractGame
{
public:
    void Init(){
        std::cout << "Football  Game Started. Enjoy the game!" << std::endl;
    }

    void Start(){
        std::cout << "Football  Game Initialized! Start playing." << std::endl;
    }

    void Stop(){
        std::cout << "Football  Game Finished!" << std::endl;
    }
};

int main()
{
    /// 玩FootBall
    std::shared_ptr<FootBall> spFootBall = std::make_shared<FootBall>();
    spFootBall->Play();

    /// 玩Cricket
    std::shared_ptr<Cricket> spCricket = std::make_shared<Cricket>();
    spCricket->Play();

    return 0;
}
